2020-2021 Sunseeker Telemetry and Lighting System
eusci_b_i2c.c
Go to the documentation of this file.
1 //*****************************************************************************
2 //
3 // eusci_b_i2c.c - Driver for the eusci_b_i2c Module.
4 //
5 //*****************************************************************************
6 
7 //*****************************************************************************
8 //
11 //
12 //*****************************************************************************
13 
14 #include "inc/hw_memmap.h"
15 
16 #ifdef __MSP430_HAS_EUSCI_Bx__
17 #include "eusci_b_i2c.h"
18 
19 #include <assert.h>
20 
21 void EUSCI_B_I2C_initMaster (uint16_t baseAddress,
22  EUSCI_B_I2C_initMasterParam *param
23  )
24 {
25  uint16_t preScalarValue;
26 
27  //Disable the USCI module and clears the other bits of control register
28  HWREG16(baseAddress + OFS_UCBxCTLW0) = UCSWRST;
29 
30  //Configure Automatic STOP condition generation
31  HWREG16(baseAddress + OFS_UCBxCTLW1) &= ~UCASTP_3;
32  HWREG16(baseAddress + OFS_UCBxCTLW1) |= (uint16_t)param->autoSTOPGeneration;
33 
34  //Byte Count Threshold
35  HWREG16(baseAddress + OFS_UCBxTBCNT) = param->byteCounterThreshold;
36  /*
37  * Configure as I2C master mode.
38  * UCMST = Master mode
39  * UCMODE_3 = I2C mode
40  * UCSYNC = Synchronous mode
41  */
42  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMST + UCMODE_3 + UCSYNC;
43 
44  //Configure I2C clock source
45  HWREG16(baseAddress + OFS_UCBxCTLW0) |= (param->selectClockSource + UCSWRST);
46 
47  /*
48  * Compute the clock divider that achieves the fastest speed less than or
49  * equal to the desired speed. The numerator is biased to favor a larger
50  * clock divider so that the resulting clock is always less than or equal
51  * to the desired clock, never greater.
52  */
53  preScalarValue = (uint16_t)(param->i2cClk / param->dataRate);
54  HWREG16(baseAddress + OFS_UCBxBRW) = preScalarValue;
55 }
56 
57 void EUSCI_B_I2C_initSlave (uint16_t baseAddress,
58  EUSCI_B_I2C_initSlaveParam *param
59  )
60 {
61  //Disable the USCI module
62  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST;
63 
64  //Clear USCI master mode
65  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCMST;
66 
67  //Configure I2C as Slave and Synchronous mode
68  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMODE_3 + UCSYNC;
69 
70  //Set up the slave address.
71  HWREG16(baseAddress + OFS_UCBxI2COA0 + param->slaveAddressOffset)
72  = param->slaveAddress + param->slaveOwnAddressEnable;
73 }
74 
75 void EUSCI_B_I2C_enable (uint16_t baseAddress)
76 {
77  //Reset the UCSWRST bit to enable the USCI Module
78  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~(UCSWRST);
79 }
80 
81 void EUSCI_B_I2C_disable (uint16_t baseAddress)
82 {
83  //Set the UCSWRST bit to disable the USCI Module
84  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST;
85 }
86 
87 void EUSCI_B_I2C_setSlaveAddress (uint16_t baseAddress,
88  uint8_t slaveAddress
89  )
90 {
91  //Set the address of the slave with which the master will communicate.
92  HWREG16(baseAddress + OFS_UCBxI2CSA) = (slaveAddress);
93 }
94 
95 void EUSCI_B_I2C_setMode (uint16_t baseAddress,
96  uint16_t mode
97  )
98 {
99  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~EUSCI_B_I2C_TRANSMIT_MODE;
100  HWREG16(baseAddress + OFS_UCBxCTLW0) |= mode;
101 }
102 
103 uint8_t EUSCI_B_I2C_getMode (uint16_t baseAddress)
104 {
105  //Read the I2C mode.
106  return ((HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTR));
107 
108 }
109 
110 void EUSCI_B_I2C_slavePutData (uint16_t baseAddress,
111  uint8_t transmitData
112  )
113 {
114  //Send single byte data.
115  HWREG16(baseAddress + OFS_UCBxTXBUF) = transmitData;
116 }
117 
118 uint8_t EUSCI_B_I2C_slaveGetData (uint16_t baseAddress)
119 {
120  //Read a byte.
121  return (HWREG16(baseAddress + OFS_UCBxRXBUF));
122 }
123 
124 uint16_t EUSCI_B_I2C_isBusBusy (uint16_t baseAddress)
125 {
126  //Return the bus busy status.
127  return (HWREG16(baseAddress + OFS_UCBxSTATW) & UCBBUSY);
128 }
129 
130 uint16_t EUSCI_B_I2C_masterIsStopSent (uint16_t baseAddress)
131 {
132  return (HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP);
133 }
134 
135 uint16_t EUSCI_B_I2C_masterIsStartSent (uint16_t baseAddress)
136 {
137  return (HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTT);
138 }
139 
140 void EUSCI_B_I2C_enableInterrupt (uint16_t baseAddress,
141  uint16_t mask
142  )
143 {
144  //Enable the interrupt masked bit
145  HWREG16(baseAddress + OFS_UCBxIE) |= mask;
146 }
147 
148 void EUSCI_B_I2C_disableInterrupt (uint16_t baseAddress,
149  uint16_t mask
150  )
151 {
152  //Disable the interrupt masked bit
153  HWREG16(baseAddress + OFS_UCBxIE) &= ~(mask);
154 }
155 
156 void EUSCI_B_I2C_clearInterrupt (uint16_t baseAddress,
157  uint16_t mask
158  )
159 {
160  //Clear the I2C interrupt source.
161  HWREG16(baseAddress + OFS_UCBxIFG) &= ~(mask);
162 }
163 
164 uint16_t EUSCI_B_I2C_getInterruptStatus (uint16_t baseAddress,
165  uint16_t mask
166  )
167 {
168  //Return the interrupt status of the request masked bit.
169  return (HWREG16(baseAddress + OFS_UCBxIFG) & mask);
170 }
171 
172 void EUSCI_B_I2C_masterSendSingleByte (uint16_t baseAddress,
173  uint8_t txData
174  )
175 {
176  //Store current TXIE status
177  uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE;
178 
179  //Disable transmit interrupt enable
180  HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);
181 
182  //Send start condition.
183  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;
184 
185  //Poll for transmit interrupt flag.
186  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
187 
188  //Send single byte data.
189  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
190 
191  //Poll for transmit interrupt flag.
192  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
193 
194  //Send stop condition.
195  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
196 
197  //Clear transmit interrupt flag before enabling interrupt again
198  HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG);
199 
200  //Reinstate transmit interrupt enable
201  HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus;
202 }
203 
204 uint8_t EUSCI_B_I2C_masterReceiveSingleByte (uint16_t baseAddress)
205 {
206  //Set USCI in Receive mode
207  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCTR;
208 
209  //Send start condition
210  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTT;
211 
212  //Poll for start condition transmission
213  while(HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTT);
214 
215  //Send stop condition
216  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
217 
218  //Poll for receive interrupt flag.
219  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG));
220 
221  //Send single byte data.
222  return (HWREG16(baseAddress + OFS_UCBxRXBUF));
223 }
224 
225 bool EUSCI_B_I2C_masterSendSingleByteWithTimeout (uint16_t baseAddress,
226  uint8_t txData,
227  uint32_t timeout
228  )
229 {
230  // Creating variable for second timeout scenario
231  uint32_t timeout2 = timeout;
232 
233  //Store current TXIE status
234  uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE;
235 
236  //Disable transmit interrupt enable
237  HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);
238 
239  //Send start condition.
240  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;
241 
242  //Poll for transmit interrupt flag.
243  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout);
244 
245  //Check if transfer timed out
246  if (timeout == 0){
247  return (STATUS_FAIL);
248  }
249 
250  //Send single byte data.
251  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
252 
253  //Poll for transmit interrupt flag.
254  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout2);
255 
256  //Check if transfer timed out
257  if (timeout2 == 0){
258  return (STATUS_FAIL);
259  }
260 
261  //Send stop condition.
262  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
263 
264  //Clear transmit interrupt flag before enabling interrupt again
265  HWREG16(baseAddress + OFS_UCBxIFG) &= ~(UCTXIFG);
266 
267  //Reinstate transmit interrupt enable
268  HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus;
269 
270  return (STATUS_SUCCESS);
271 }
272 
273 void EUSCI_B_I2C_masterSendMultiByteStart (uint16_t baseAddress,
274  uint8_t txData
275  )
276 {
277  //Store current transmit interrupt enable
278  uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE;
279 
280  //Disable transmit interrupt enable
281  HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);
282 
283  //Send start condition.
284  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;
285 
286  //Poll for transmit interrupt flag.
287  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
288 
289  //Send single byte data.
290  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
291 
292  //Reinstate transmit interrupt enable
293  HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus;
294 }
295 
296 bool EUSCI_B_I2C_masterSendMultiByteStartWithTimeout (uint16_t baseAddress,
297  uint8_t txData,
298  uint32_t timeout
299  )
300 {
301  //Store current transmit interrupt enable
302  uint16_t txieStatus = HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE;
303 
304  //Disable transmit interrupt enable
305  HWREG16(baseAddress + OFS_UCBxIE) &= ~(UCTXIE);
306 
307  //Send start condition.
308  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTR + UCTXSTT;
309 
310  //Poll for transmit interrupt flag.
311  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout);
312 
313  //Check if transfer timed out
314  if (timeout == 0){
315  return (STATUS_FAIL);
316  }
317 
318  //Send single byte data.
319  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
320 
321  //Reinstate transmit interrupt enable
322  HWREG16(baseAddress + OFS_UCBxIE) |= txieStatus;
323 
324  return(STATUS_SUCCESS);
325 }
326 
327 void EUSCI_B_I2C_masterSendMultiByteNext (uint16_t baseAddress,
328  uint8_t txData
329  )
330 {
331  //If interrupts are not used, poll for flags
332  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
333  //Poll for transmit interrupt flag.
334  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
335  }
336 
337  //Send single byte data.
338  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
339 }
340 
341 bool EUSCI_B_I2C_masterSendMultiByteNextWithTimeout (uint16_t baseAddress,
342  uint8_t txData,
343  uint32_t timeout
344  )
345 {
346  //If interrupts are not used, poll for flags
347  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
348  //Poll for transmit interrupt flag.
349  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout);
350 
351  //Check if transfer timed out
352  if (timeout == 0){
353  return (STATUS_FAIL);
354  }
355  }
356 
357  //Send single byte data.
358  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
359 
360  return(STATUS_SUCCESS);
361 }
362 
363 void EUSCI_B_I2C_masterSendMultiByteFinish (uint16_t baseAddress,
364  uint8_t txData
365  )
366 {
367  //If interrupts are not used, poll for flags
368  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
369  //Poll for transmit interrupt flag.
370  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
371  }
372 
373  //Send single byte data.
374  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
375 
376  //Poll for transmit interrupt flag.
377  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
378 
379  //Send stop condition.
380  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
381 }
382 
383 bool EUSCI_B_I2C_masterSendMultiByteFinishWithTimeout (uint16_t baseAddress,
384  uint8_t txData,
385  uint32_t timeout
386  )
387 {
388  uint32_t timeout2 = timeout;
389 
390  //If interrupts are not used, poll for flags
391  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
392  //Poll for transmit interrupt flag.
393  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) ;
394 
395  //Check if transfer timed out
396  if (timeout == 0){
397  return (STATUS_FAIL);
398  }
399  }
400 
401  //Send single byte data.
402  HWREG16(baseAddress + OFS_UCBxTXBUF) = txData;
403 
404  //Poll for transmit interrupt flag.
405  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout2) ;
406 
407  //Check if transfer timed out
408  if (timeout2 == 0){
409  return (STATUS_FAIL);
410  }
411 
412  //Send stop condition.
413  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
414 
415  return(STATUS_SUCCESS);
416 }
417 
418 void EUSCI_B_I2C_masterSendStart (uint16_t baseAddress)
419 {
420  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTT;
421 }
422 
423 void EUSCI_B_I2C_masterSendMultiByteStop (uint16_t baseAddress)
424 {
425  //If interrupts are not used, poll for flags
426  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
427  //Poll for transmit interrupt flag.
428  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) ;
429  }
430 
431  //Send stop condition.
432  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
433 }
434 
435 bool EUSCI_B_I2C_masterSendMultiByteStopWithTimeout (uint16_t baseAddress,
436  uint32_t timeout)
437 {
438  //If interrupts are not used, poll for flags
439  if (!(HWREG16(baseAddress + OFS_UCBxIE) & UCTXIE)){
440  //Poll for transmit interrupt flag.
441  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCTXIFG)) && --timeout) ;
442 
443  //Check if transfer timed out
444  if (timeout == 0){
445  return (STATUS_FAIL);
446  }
447  }
448 
449  //Send stop condition.
450  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
451 
452  return (STATUS_SUCCESS);
453 }
454 
455 void EUSCI_B_I2C_masterReceiveStart (uint16_t baseAddress)
456 {
457  //Set USCI in Receive mode
458  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCTR;
459  //Send start
460  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTT;
461 }
462 
463 uint8_t EUSCI_B_I2C_masterReceiveMultiByteNext (uint16_t baseAddress)
464 {
465  return (HWREG16(baseAddress + OFS_UCBxRXBUF));
466 }
467 
468 uint8_t EUSCI_B_I2C_masterReceiveMultiByteFinish (uint16_t baseAddress)
469 {
470  //Send stop condition.
471  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
472 
473  //Wait for Stop to finish
474  while (HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP)
475 
476  // Wait for RX buffer
477  while (!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG)) ;
478 
479  //Capture data from receive buffer after setting stop bit due to
480  //MSP430 I2C critical timing.
481  return (HWREG16(baseAddress + OFS_UCBxRXBUF));
482 }
483 
484 bool EUSCI_B_I2C_masterReceiveMultiByteFinishWithTimeout (uint16_t baseAddress,
485  uint8_t *txData,
486  uint32_t timeout
487  )
488 {
489  uint32_t timeout2 = timeout;
490 
491  //Send stop condition.
492  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
493 
494  //Wait for Stop to finish
495  while ((HWREG16(baseAddress + OFS_UCBxCTLW0) & UCTXSTP) && --timeout);
496 
497  //Check if transfer timed out
498  if (timeout == 0){
499  return (STATUS_FAIL);
500  }
501 
502  // Wait for RX buffer
503  while ((!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG)) && --timeout2);
504 
505  //Check if transfer timed out
506  if (timeout2 == 0){
507  return (STATUS_FAIL);
508  }
509 
510  //Capture data from receive buffer after setting stop bit due to
511  //MSP430 I2C critical timing.
512  *txData = (HWREG8(baseAddress + OFS_UCBxRXBUF));
513 
514  return (STATUS_SUCCESS);
515 }
516 
517 void EUSCI_B_I2C_masterReceiveMultiByteStop (uint16_t baseAddress)
518 {
519  //Send stop condition.
520  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCTXSTP;
521 }
522 
523 void EUSCI_B_I2C_enableMultiMasterMode(uint16_t baseAddress)
524 {
525  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST;
526  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCMM;
527 }
528 
529 void EUSCI_B_I2C_disableMultiMasterMode(uint16_t baseAddress)
530 {
531 
532  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST;
533  HWREG16(baseAddress + OFS_UCBxCTLW0) &= ~UCMM;
534 }
535 
536 uint8_t EUSCI_B_I2C_masterReceiveSingle (uint16_t baseAddress)
537 {
538  //Polling RXIFG0 if RXIE is not enabled
539  if(!(HWREG16(baseAddress + OFS_UCBxIE) & UCRXIE0)) {
540  while(!(HWREG16(baseAddress + OFS_UCBxIFG) & UCRXIFG0));
541  }
542 
543  //Read a byte.
544  return (HWREG16(baseAddress + OFS_UCBxRXBUF));
545 }
546 
547 uint32_t EUSCI_B_I2C_getReceiveBufferAddress (uint16_t baseAddress)
548 {
549  return ( baseAddress + OFS_UCBxRXBUF );
550 }
551 
552 uint32_t EUSCI_B_I2C_getTransmitBufferAddress (uint16_t baseAddress)
553 {
554  return ( baseAddress + OFS_UCBxTXBUF );
555 }
556 void EUSCI_B_I2C_setTimeout(uint16_t baseAddress, uint16_t timeout)
557 {
558  uint16_t tempUCBxCTLW0;
559 
560  //Save value of UCSWRST bit before we disable eUSCI module
561  tempUCBxCTLW0 = HWREG16(baseAddress + OFS_UCBxCTLW0);
562  //Disable the USCI module
563  HWREG16(baseAddress + OFS_UCBxCTLW0) |= UCSWRST;
564 
565  //Set timeout
566  HWREG16(baseAddress + OFS_UCBxCTLW1) = (HWREG16(baseAddress + OFS_UCBxCTLW1) & (~UCCLTO_3)) | timeout;
567 
568  //Restore value of UCSWRST bit
569  HWREG16(baseAddress + OFS_UCBxCTLW0) = tempUCBxCTLW0;
570 }
571 
572 #endif
573 //*****************************************************************************
574 //
577 //
578 //*****************************************************************************
uint8_t transmitData
MPU_initThreeSegmentsParam param
#define HWREG8(x)
Definition: hw_memmap.h:41
#define HWREG16(x)
Definition: hw_memmap.h:39
#define STATUS_FAIL
Definition: hw_memmap.h:23
#define STATUS_SUCCESS
Definition: hw_memmap.h:22